<?php

declare (strict_types=1);

namespace app\common\service\user;

use app\common\exception\AdminException;
use app\common\service\BaseService;
use app\common\repository\user\UserAccountRepository;
use app\common\service\CodexPriceService;
use think\facade\Db;

class UserAccountService extends BaseService
{
    public function __construct(UserAccountRepository $repository)
    {
        $this->repository = $repository;
    }

    /**
     * 获取用户账号详情
     *
     * @param $user_id
     * @return \app\common\model\BaseModel|array|mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getUserAccountInfo($user_id): mixed
    {
        // 如果没有先新建
        $userIncomeSummary = Db::name('user_income_summary')->where('user_id', $user_id)->find();
        if(!$userIncomeSummary){
            Db::name('user_income_summary')->insert(['user_id' => $user_id, 'last_update_time' => time()]);
        }

        $userInfo = Db::name('user_account')
            ->alias('ua')
            ->join('user_income_summary uis', 'ua.user_id = uis.user_id')
            ->where('ua.user_id', $user_id)
            ->find();


        $userInfo['personalTotalPoaUsdt'] = Db::name('user_investment')->where('status', 1)->where('user_id', $user_id)->sum('usdt_amount'); // 个人总算力
        $userInfo['personalTotalLdPoaUsdt'] = Db::name('user_investment')->where('status', 1)->where('mode', 1)->where('user_id', $user_id)->sum('usdt_amount'); // 个人流动性
        $userInfo['personalTotalNrPoaUsdt'] = Db::name('user_investment')->where('status', 1)->where('mode', 2)->where('user_id', $user_id)->sum('usdt_amount'); // 个人内容铸造
        $userInfo['personalTotalNrPoaCodex'] = Db::name('user_investment')->where('status', 1)->where('mode', 2)->where('user_id', $user_id)->sum('codex_amount'); // 个人内容铸造
        $userInfo['personalTotalPoaCodex'] = Db::name('user_investment')->where('status', 1)->where('user_id', $user_id)->sum('codex_amount');
        $dirUserIds = Db::name('user')->where('status', 1)->where('pid', $user_id)->column('id');
        if(!empty($dirUserIds)) {
            $userInfo['dirUserTotalPoaUsdt'] = Db::name('user_investment')->where('mode', 2)->where('status', 1)->whereIn('user_id', $dirUserIds)->sum('usdt_amount'); // 推荐poa算力
        } else {
            $userInfo['dirUserTotalPoaUsdt'] = 0;
        }
        // 团队方面
        $TeamIds = Db::name('user')->where('status', 1)->where('id', '<>', $user_id)->where('path', 'like', '%,' . $user_id . ',%')->column('id');
        $userInfo['teamMemberCount'] = Db::name('user')->where('status', 1)->where('pid', $user_id)->count(); // 推荐人数
        $userInfo['teamTotalPoa'] = Db::name('user_investment')->where('status', 1)->whereIn('user_id', $TeamIds)->sum('usdt_amount'); // 社区poa总算里
        $userInfo['teamTotalCastingPoa'] = Db::name('user_investment')->where('status', 1)->where('mode', 2)->whereIn('user_id', $TeamIds)->sum('usdt_amount'); // 社区内容铸造算力
        $userInfo['teamTotalLiquidityPoa'] = Db::name('user_investment')->where('status', 1)->where('mode', 1)->whereIn('user_id', $TeamIds)->sum('usdt_amount'); // 社区流动性算力
        return $userInfo;
    }

    /**
     * 添加用户钱包
     *
     * @param array $data
     * @return \app\common\model\BaseModel|array|\think\Collection|\think\model\contract\Modelable
     * @throws \Exception
     */
    public function add(array $data): \think\model\contract\Modelable|\think\Collection|\app\common\model\BaseModel|array
    {
        return $this->repository->save([
            'user_id' => $data['user_id'],
            'address' => $data['address'],
            'coin_balance' => 0,
            'usdt_balance' => 0
        ]);
    }

    /**
     * coddex兑换usdt
     *
     * @param $user_id
     * @param $amount
     * @return mixed
     */
    public function codexExchangeUSDT($user_id, $amount): mixed
    {
        return $this->transaction(function () use ($user_id, $amount) {
            $codexAmount = $amount;
            $currentCodexPrice = app()->make(CodexPriceService::class)->getNewPrice();
//            $accountCodexAmount = $this->repository->getValue('codex_balance', [
//                'user_id' => $user_id,
//            ]);
            $accountCodexAmount = Db::name('user_account')->where('user_id', $user_id)->lock(true)->value('codex_balance');
            if ($accountCodexAmount < $codexAmount) {
                throw new AdminException('Insufficient balance');
            }
            $usdtAmount = $codexAmount * $currentCodexPrice;

            // 更新用户钱包：减少CODEX余额，增加USDT余额
            $updateCodexResult = $this->repository->setInc(['user_id' => $user_id], 'codex_balance', 'dec', $amount);
            $updateUsdtResult = $this->repository->setInc(['user_id' => $user_id], 'usdt_balance', 'inc', $usdtAmount);

            if (!$updateCodexResult || !$updateUsdtResult) {
                throw new AdminException('Failed to update wallet balances');
            }

            // 记录兑换交易到`cc_user_exchange_record`
            $exchangeRecordData = [
                'user_id' => $user_id,
                'exchange_type' => 'codex_to_usdt',
                'amount_from' => $amount,
                'amount_to' => $usdtAmount,
                'from_currency' => 'CODEX',
                'to_currency' => 'USDT',
                'exchange_rate' => $currentCodexPrice,
                'status' => 'success',
                'create_time' => time(),
            ];
            $userExchangeRecordService = app()->make(UserExchangeRecordService::class);
            $userExchangeRecordService->create($exchangeRecordData);
            return true;
        });
    }

    /**
     * 用户提现USDT
     *
     * @param $user_id
     * @param $amount
     * @param $tx_hash
     * @return mixed
     */
    public function userWithdraw($user_id, $amount, $tx_hash): mixed
    {
        // 1. 获取用户 USDT 余额
        $usdtBalance = $this->repository->getValue('usdt_balance', [
            'user_id' => $user_id,
        ]);

        if ($usdtBalance < $amount) {
            throw new AdminException('Insufficient balance');
        }

        // 2. 获取用户钱包地址（假设在用户表或账户表中）
        $address = $this->repository->getValue('address', [
            'user_id' => $user_id,
        ]);

        if (empty($address)) {
            throw new AdminException('Wallet address not set');
        }

        // 3. 假设手续费为固定值或按比例计算（示例：1 USDT 手续费）
        $fee = $amount * 0.02; // 可改为配置或计算逻辑
        $actualAmount = $amount - $fee;

        if ($actualAmount <= 0) {
            throw new AdminException('Actual amount after fee is invalid');
        }

        return $this->transaction(function () use ($user_id, $amount, $fee, $actualAmount, $address, $tx_hash) {
            // 1. 扣减前先获取当前余额（快照）
            $currentBalance = $this->repository->getValue('usdt_balance', [
                'user_id' => $user_id,
            ]);

            // 2. 计算变动后余额
            $balanceAfter = $currentBalance - $amount;

            if ($balanceAfter < 0) {
                throw new AdminException('Balance cannot be negative after withdrawal');
            }

            // 3. 创建提现记录
            $userWithdrawService = app()->make(UserWithdrawService::class);
            $withdrawData = [
                'user_id' => $user_id,
                'address' => $address,
                'coin_type' => 'usdt',
                'amount' => $amount,
                'fee' => $fee,
                'actual_amount' => $actualAmount,
                'tx_hash' => $tx_hash,
                'status' => 'pending',
                'create_time' => time(),
                'update_time' => time(),
            ];
            $withdrawId = $userWithdrawService->create($withdrawData);
            if (!$withdrawId) {
                throw new AdminException('Failed to create withdraw record');
            }

            // 4. 扣减用户余额（在获取余额之后执行）
            $this->repository->setInc(['user_id' => $user_id], 'usdt_balance', 'dec', $amount);

            // 5. 记录余额变动日志（使用预先计算的 balanceAfter）
            $logService = app()->make(UserBalanceLogService::class);
            $logService->addLog(
                $user_id,
                'withdraw_apply',
                'usdt',
                $amount,
                "WIT{$withdrawId}",
                "提现申请: {$amount} USDT",
                'decrease'
            );

            return [
                'withdraw_id' => $withdrawId,
                'amount' => $amount,
                'fee' => $fee,
                'actual_amount' => $actualAmount,
                'address' => $address,
                'balance_after' => round($balanceAfter, 8)
            ];
        });
    }
}